package com.starview.platform.data.type;

import java.util.Collection;

import com.starview.star.compiler.standard.StandardNames;
import com.starview.star.compiler.type.Dictionary;
import com.starview.star.compiler.util.FixedList;
import com.starview.star.compiler.util.PrettyPrintDisplay;
import com.starview.star.compiler.util.PrettyPrintable;

/**
 * A tuple constraint is imposed on a type variable if the variable must be bound to a tuple of some
 * arity
 * 
 * @author fgm
 * 
 */
@SuppressWarnings("serial")
public class TupleConstraint implements ITypeConstraint, PrettyPrintable
{
  private final TypeVar var;

  public TupleConstraint(TypeVar con)
  {
    this.var = con;
  }

  @Override
  public Collection<TypeVar> affectedVars()
  {
    return FixedList.create(var);
  }

  @Override
  public void checkBinding(IType candidate, Location loc, Dictionary dict) throws TypeConstraintException
  {
    if (!TypeUtils.isTupleType(candidate))
      throw new TypeConstraintException("must be a tuple type", loc);
  }

  @Override
  public boolean sameConstraint(ITypeConstraint other, Location loc, Dictionary dict) throws TypeConstraintException
  {
    return other instanceof TupleConstraint;
  }

  @Override
  public void accept(ITypeVisitor visitor)
  {
    var.accept(visitor);
  }

  @Override
  public <T, C> C transform(TypeTransformer<T, C> trans)
  {
    return trans.transformTupleContraint(this);
  }

  public IType getVar()
  {
    return var;
  }

  @Override
  public void prettyPrint(PrettyPrintDisplay disp)
  {
    showConstraint(new DisplayType(disp));
  }

  @Override
  public void showConstraint(DisplayType disp)
  {
    var.accept(disp);
    disp.getDisp().appendWord(StandardNames.IS_TUPLE);
  }
}
